﻿#include "ssMeshRender.h"
#include "../material/ssMaterial.h"
#include "../../resmgr/ssResManager.h"


namespace StarSeeker
{

ssMeshRender::ssMeshRender()
{
	m_type = SS_COMPONENT_RENDER;
	m_VDF = 0;
	m_index = 0;
	m_vertex = 0;
	m_normal = 0;
	m_tangent = 0;
	m_primitiveType = SS_PRIMITIVE_TRIANGLE;
	m_pMesh = 0;
	m_queTag = SS_QUE_GEOMERY;
	m_distance = 0;
}

ssMeshRender::~ssMeshRender()
{
	if (m_pMesh)
	{
		SS_RES_MANAGR->RecoverRes(m_pMesh);
	}
	else
	{
		SS_SAFE_DELETE(m_vertex)
		SS_SAFE_DELETE(m_index)
		SS_SAFE_DELETE(m_normal)
		SS_SAFE_DELETE(m_tangent)
	}
}

void ssMeshRender::Render()
{
	if (m_VDF&SS_VDF_INDEX)
	{
		glDrawElements(m_primitiveType, m_index->m_indexCount, m_index->m_bitType, 0);
	}
	else
	{
		glDrawArrays(m_primitiveType, 0, 3);
	}
	CheckGlError("Render");
}

bool ssMeshRender::SetVertex(u32 num, const ssfloat* pv)
{
	if (!(m_VDF&SS_VDF_VERTEX_3F))
	{
		SS_SAFE_NEW(m_vertex, ssVBOBind)
		if (m_vertex->CreateFloat(pv, num))
		{
			m_VDF |= SS_VDF_VERTEX_3F;
			m_vertexAttrib.BindData(3, SS_FLOAT, 0, 0, "inPosition");
			return true;
		}
		SS_SAFE_DELETE(m_vertex)
	}
	return false;
}

bool ssMeshRender::SetIndex(u32 num, const void* pi, u32 bit)
{
	if (!(m_VDF&SS_VDF_INDEX))
	{
		SS_SAFE_NEW(m_index, ssIBOBind)
		if (m_index->Create(bit, pi, num))
		{
			m_VDF |= SS_VDF_INDEX;
			return true;
		}
		SS_SAFE_DELETE(m_index)
	}
	return false;
}

bool ssMeshRender::SetNormal(u32 num, const ssfloat* pn)
{
	if (!(m_VDF&SS_VDF_NORMAL_3F))
	{
		SS_SAFE_NEW(m_normal, ssVBOBind)
		if (m_normal->CreateFloat(pn, num))
		{
			m_VDF |= SS_VDF_NORMAL_3F;
			m_normalAttrib.BindData(3, SS_FLOAT, 0, 0, "inNormal");
			return true;
		}
		SS_SAFE_DELETE(m_normal)
	}
	return false;
}

bool ssMeshRender::SetTangent(u32 num, const ssfloat * pt)
{
	if (!(m_VDF&SS_VDF_TANGENT_3F))
	{
		SS_SAFE_NEW(m_tangent, ssVBOBind)
		if (m_tangent->CreateFloat(pt, num))
		{
			m_VDF |= SS_VDF_TANGENT_3F;
			m_tangentAttrib.BindData(3, SS_FLOAT, 0, 0, "inTangent");
			return true;
		}
		SS_SAFE_DELETE(m_normal)
	}
	return false;
}

void ssMeshRender::SetDataFromMesh(const char* uri)
{
	ssMesh* pMesh = SS_DYNAMIC_CAST(ssMesh*, SS_RES_MANAGR->QuoteResByUri(uri));
	if (pMesh)
	{
		m_pMesh = pMesh;
		m_vertex = pMesh->GetVertexVBO();
		m_index = pMesh->GetVertexIBO();
		m_normal = pMesh->GetNormalVBO();
		m_tangent = pMesh->GetTangentVBO();
		if (m_vertex)
		{
			m_VDF |= SS_VDF_VERTEX_3F;
			m_vertexAttrib.BindData(3, SS_FLOAT, 0, 0, "inPosition");
		}
		if (m_index)
		{
			m_VDF |= SS_VDF_INDEX;
		}
		if (m_normal)
		{
			m_VDF |= SS_VDF_NORMAL_3F;
			m_normalAttrib.BindData(3, SS_FLOAT, 0, 0, "inNormal");
		}
		if (m_tangent)
		{
			m_VDF |= SS_VDF_TANGENT_3F;
			m_tangentAttrib.BindData(3, SS_FLOAT, 0, 0, "inTangent");
		}
	}
}

void ssMeshRender::SetVDF(u32 es)
{
	m_VDF |= es;
	if (es==SS_ES_ALPHA)
	{
		m_queTag = SS_QUE_ALPHA;
	}
}

void ssMeshRender::OnRenderBegin()
{
	if (m_VDF&SS_VDF_VERTEX_3F)
	{
		m_vertex->Use();
		m_vertexAttrib.Use(ssMaterial::s_pShader);
	}
	if (m_VDF&SS_VDF_INDEX)
	{
		m_index->Use();
	}
	if (m_VDF&SS_VDF_NORMAL_3F)
	{
		m_normal->Use();
		m_normalAttrib.Use(ssMaterial::s_pShader);
	}
	if (m_VDF&SS_VDF_TANGENT_3F)
	{
		m_tangent->Use();
		m_tangentAttrib.Use(ssMaterial::s_pShader);
	}
}

void ssMeshRender::OnRenderEnd()
{
	if (m_VDF&SS_VDF_INDEX)
	{
		m_index->Nonuse();
		m_vertexAttrib.Nonuse();
	}
	if (m_VDF&SS_VDF_VERTEX_3F)
	{
		m_vertex->Nonuse();
	}
	if (m_VDF&SS_VDF_NORMAL_3F)
	{
		m_normal->Nonuse();
		m_normalAttrib.Nonuse();
	}
	if (m_VDF&SS_VDF_TANGENT_3F)
	{
		m_tangent->Nonuse();
		m_tangentAttrib.Nonuse();
	}
}

}
